package org.charry.lib.config;

import java.sql.*;
import java.util.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.charry.lib.database_utility.DatabaseFactory;
import org.charry.lib.database_utility.DatabaseFactory.ResultSetEx;

public class Konfig {
	private Konfig() {
		if (configTable.trim().equals(""))
			configTable = "SYSTEM_CONFIG";
	}

	public static void setDatabaseAlias(String dbAlias) {
		databaseAlias = dbAlias;
	}

	public static synchronized Konfig Instance() {
		if (databaseAlias.trim().equals(""))
			return null;

		if (instance == null)
			instance = new Konfig();

		// if the config item is out-of-date, then reload it
		instance.reloadConfig();

		return instance;
	}

	/**
	 * specify the config table, the default config table is SYSTEM_CONFIG if
	 * the client code doesn't specify a config table
	 * 
	 * @param tableName
	 */
	public static void setConfigTable(String tableName) {
		configTable = tableName;
	}

	/**
	 * check the time and reload the config from database, if it's expired
	 * 
	 */
	private void reloadConfig() {
		long lNow = new java.util.Date().getTime();

		if (lNow - lastCheckPoint > EXPIRE_OFFSET)
			loadConfig();
	}

	public boolean getBoolean(String name) {
		boolean value = false;
		try {
			value = Boolean.parseBoolean(configItemHashMap.get(name));
		} catch (Exception e) {
			log.info("warning: failed to get config(getBoolean):" + name);
		}

		return value;
	}

	public boolean getBoolean(String name, boolean d) {
		boolean value = false;
		try {
			String tmp = configItemHashMap.get(name);
			if (tmp == null)
				value = d;
			else
				value = Boolean.parseBoolean(configItemHashMap.get(name));
		} catch (Exception e) {
			log.info("warning: failed to get config(getBoolean):" + name
					+ ", use deault:" + d);
			value = d;
		}

		return value;
	}

	public String getString(String name) {
		String value = null;
		try {
			value = configItemHashMap.get(name);
		} catch (Exception e) {
			log.info("warning: failed to get config(getString):" + name);
		}

		if (value == null)
			value = "";

		return value;
	}

	/**
	 * get string config from database
	 * 
	 * @param name
	 *            name of config
	 * @param d
	 *            default value of config
	 * @return value of config item
	 */
	public String getString(String name, String d) {
		String value = getString(name);

		if (value.equals("")) {
			value = d;
			log.info("warning: failed to get config(getString):" + name
					+ ", use default:" + d);
		}

		return value;
	}

	public int getInt(String name) {
		int value = Integer.MIN_VALUE;
		try {
			value = Integer.parseInt(configItemHashMap.get(name));
		} catch (Exception e) {
			log.info("warning: failed to get config(getInt):" + name);
		}

		return value;
	}

	public int getInt(String name, int d) {
		int value = Integer.MIN_VALUE;

		value = getInt(name);
		if (value == Integer.MIN_VALUE) {
			value = d;
			log.info("warning: failed to get config(getInt):" + name
					+ "use default:" + d);
		}

		return value;
	}

	public double getDouble(String name) {
		double value = Double.MIN_VALUE;

		try {
			value = Double.parseDouble(configItemHashMap.get(name));
		} catch (Exception e) {
			log.info("warning: failed to get config(getDouble):" + name);
		}

		return value;
	}

	public double getDouble(String name, double d) {
		double value = Double.MIN_VALUE;
		value = getDouble(name);

		if (value == Double.MIN_VALUE) {
			value = d;
			log.info("warning: failed to get config(getDouble):" + name
					+ "use default:" + d);
		}

		return value;
	}

	public float getFloat(String name) {
		float value = Float.MIN_VALUE;

		try {
			value = Float.parseFloat(configItemHashMap.get(name));
		} catch (Exception e) {
			log.info("warning: failed to get config(getFloat):" + name);
		}

		return value;
	}

	public float getFloat(String name, float d) {
		float value = Float.MIN_VALUE;
		value = getFloat(name);

		if (value == Float.MIN_VALUE) {
			value = d;
			log.info("warning: failed to get config(getFloat):" + name
					+ ", use default:" + d);
		}

		return value;
	}

	private HashMap<String, String> loadConfig() {
		if (configItemHashMap != null)
			configItemHashMap.clear();

		String sql = "SELECT * FROM " + configTable;
		ResultSetEx rx = null;
		configItemHashMap.clear();

		try {
			rx = DatabaseFactory.getInstance(databaseAlias).executeQueryEx(sql);
			while (rx.getResultSet().next()) {
				configItemHashMap.put(rx.getResultSet().getString("NAME")
						.trim(), rx.getResultSet().getString("VALUE").trim());
			}
		} catch (SQLException e) {
			log.error("failed to get config from database:" + e);
		} finally {
			rx.close();
		}

		log.info("load config from database:" + databaseAlias);

		return configItemHashMap;
	}

	private static Konfig instance = null;
	private static Log log = LogFactory.getLog(Konfig.class);
	private static HashMap<String, String> configItemHashMap = new HashMap<String, String>();
	private static long lastCheckPoint = 0;
	private static int EXPIRE_OFFSET = 1 * 3600 * 1000;
	private static String configTable = "";
	private static String databaseAlias = "";
}
